package com.heima.user.service.impl;
import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.message.FollowBehaviorConstants;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.behavior.dtos.FollowBehaviorDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.dtos.UserRelationDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.ApUserFan;
import com.heima.model.user.pojos.ApUserFollow;
import com.heima.user.feign.ArticleFeign;
import com.heima.user.mapper.ApUserFanMapper;
import com.heima.user.mapper.ApUserFollowMapper;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.ApUserRelationService;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @作者 itcast
 * @创建日期 2021/2/3 14:26
 **/
@Service
@Slf4j
@Transactional
public class ApUserRelationServiceImpl implements ApUserRelationService {

    @Autowired
    ArticleFeign articleFeign;

    @Autowired
    ApUserMapper apUserMapper;

    @Override
    public ResponseResult follow(UserRelationDto dto) {
        log.info("follow 方法传进来的参数==> {}",dto);
        // 1. 检查参数
        if(dto == null || dto.getAuthorId() == null || dto.getArticleId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // operation    不能为null and ( 0 or 1)
        if(dto.getOperation() == null||(dto.getOperation()!=0&&dto.getOperation()!=1)){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 2. 查询作者id对应的作者信息，作者信息对应的用户信息
        ApAuthor apAuthor = articleFeign.selectById(dto.getAuthorId());
        if(apAuthor == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"作者信息不存在");
        }
        ApUser followUser = apUserMapper.selectById(apAuthor.getUserId());
        // 3. 查询当前登录用户对应的用户信息
        ApUser currentUser = apUserMapper.selectById(AppThreadLocalUtils.getUser().getId());
        if(currentUser == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"当前登录用户不存在");
        }
        // 4. 根据dto中 关注 或 取消 进行对应的操作
        if(dto.getOperation() == 0){
            return followAuthor(followUser,currentUser,dto.getArticleId());
        }else {
            return cancelFollowAuthor(followUser,currentUser);
        }
    }
    @Autowired
    ApUserFollowMapper apUserFollowMapper;
    @Autowired
    ApUserFanMapper apUserFanMapper;
    /**
     * 取关作者
     * @param followUser
     * @param currentUser
     * @return
     */
    private ResponseResult cancelFollowAuthor(ApUser followUser, ApUser currentUser) {
        // 1. 检查有没有关注过这个作者
        ApUserFollow apUserFollow = apUserFollowMapper.selectOne(
                Wrappers.<ApUserFollow>lambdaQuery()
                        .eq(ApUserFollow::getUserId, currentUser.getId())
                        .eq(ApUserFollow::getFollowId, followUser.getId())
        );
        if (apUserFollow == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"你没关注过该作者");
        }
        // 2. 删除关注信息
        apUserFollowMapper.deleteById(apUserFollow.getId());

        // 3. 删除对应粉丝信息
        apUserFanMapper.delete(
                Wrappers.<ApUserFan>lambdaQuery()
                        .eq(ApUserFan::getFansId,currentUser.getId())
                        .eq(ApUserFan::getUserId,followUser.getId())
        );
        return ResponseResult.okResult();
    }

    @Autowired
    KafkaTemplate<String,String> kafkaTemplate;

    /**
     * 关注作者
     * @param followUser 要关注的人
     * @param currentUser 当前登录人
     * @return
     */
    private ResponseResult followAuthor(ApUser followUser, ApUser currentUser,Long articleId) {
        // 1. 检查有没有关注过这个作者
        ApUserFollow apUserFollow = apUserFollowMapper.selectOne(
                Wrappers.<ApUserFollow>lambdaQuery()
                        .eq(ApUserFollow::getUserId, currentUser.getId())
                        .eq(ApUserFollow::getFollowId, followUser.getId())
        );
        // 2. 如果关注过，直接提示关注过
        if(apUserFollow!=null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"您已关注过该作者");
        }
        // 3. 如果没有关注， 添加一条关注信息
        apUserFollow = new ApUserFollow();
        apUserFollow.setUserId(currentUser.getId());
        apUserFollow.setFollowId(followUser.getId());
        apUserFollow.setFollowName(followUser.getName());
        apUserFollow.setLevel((short)0);
        apUserFollow.setIsNotice(false);
        apUserFollow.setCreatedTime(new Date());
        apUserFollowMapper.insert(apUserFollow);
        // 4. 添加一条粉丝信息
        ApUserFan apUserFan = apUserFanMapper.selectOne(
                Wrappers.<ApUserFan>lambdaQuery()
                        .eq(ApUserFan::getFansId, currentUser.getId())
                        .eq(ApUserFan::getUserId, followUser.getId())
        );
        if (apUserFan==null){
            apUserFan = new ApUserFan();
            apUserFan.setUserId(followUser.getId());
            apUserFan.setFansId(Long.valueOf(currentUser.getId()));
            apUserFan.setFansName(currentUser.getName());
            apUserFan.setLevel((short)0);
            apUserFan.setCreatedTime(new Date());
            apUserFan.setIsDisplay(false);
            apUserFan.setIsShieldLetter(false);
            apUserFan.setIsShieldComment(false);
            apUserFanMapper.insert(apUserFan);
        }
        // 用于发送到关注行为的消息
        FollowBehaviorDto dto = new FollowBehaviorDto();
        dto.setArticleId(articleId);
        dto.setFollowId(followUser.getId());
        dto.setUserId(currentUser.getId());
        kafkaTemplate.send(FollowBehaviorConstants.FOLLOW_BEHAVIOR_TOPIC, JSON.toJSONString(dto));
        return ResponseResult.okResult();
    }
}
